import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security .*;
import java.security .spec .*;

import javax.crypto .*;
import javax.crypto . spec .*;
/**
 * encrypt.java - This class takes in a string at a time, and encrypts the string
 *   
 * @author Marc Vandehey
 */
public class encrypt {
	private static Cipher encrypter;
	private static Cipher decrypter;
	private static SecretKey key;
	private static PublicKey user_pub_key;
	private static PrivateKey user_private_key;
	/**
	 * Takes in a string, and encrypts it using sun.misc.BASE64Encoder
	 * 
	 * @param text Text to encrypt
	 * @return Encrypted string
	 */
	public static String encrypter (String text) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException 
	{
		encrypter = Cipher.getInstance("des");
		encrypter.init(Cipher.ENCRYPT_MODE, key);

		// Encode the string into bytes using utf-8
		byte[] utf8 = text.getBytes("UTF8");
		// Encrypt
		byte[] enc = encrypter.doFinal(utf8);
		// Encode bytes to base64 to get a string
		return new sun.misc.BASE64Encoder().encode(enc); 

	}
	/**
	 * Takes in a string, and makes a SecretKey and saves it for later use.
	 * It will be used to encrypt the body using DES encryption.
	 * 
	 * @param keyIn string to make a SecretKey
	 * @return Void
	 */
	public static void makeSymmetricKey (String keyIn) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException 
	{
		byte[] desKeyData = keyIn.getBytes();
		DESKeySpec desKeySpec = new DESKeySpec(desKeyData);
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		key = keyFactory.generateSecret(desKeySpec);
		encrypter = Cipher.getInstance("DES");
		decrypter = Cipher.getInstance("DES");
		encrypter.init(Cipher.ENCRYPT_MODE, key);
		decrypter.init(Cipher.DECRYPT_MODE, key); 
	}
	/**
	 * Takes in a string, and decrypts it using sun.misc.BASE64Decoder
	 * 
	 * @param text Text to decrypt
	 * @return Decrypted string
	 */
	public static String decrypt (String text) throws IOException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException
	{
		decrypter = Cipher.getInstance("des");
		decrypter.init(Cipher.DECRYPT_MODE, key); 
		
		// Decode base64 to get bytes
		byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(text);
		// Decrypt
		byte[] utf8 = decrypter.doFinal(dec);
		// Decode using utf-8
		return new String(utf8, "UTF8"); 
	}
	/**
	 * To ensure privacy set all of the RSA keys to null
	 * 
	 * @return Void
	 */
	private static void clearKeys()
	{
		user_pub_key = null;
		user_private_key = null;
	}
	/**
	 * Reads the public key file, and sets the private variable user_pub_key to the correct public key
	 * 
	 * @return Void
	 * @throws NoSuchAlgorithmException 
	 * @throws IOException 
	 * @throws InvalidKeySpecException 
	 */
	private static void setUserPubKey() throws NoSuchAlgorithmException, IOException, InvalidKeySpecException
	{
		//look in file user.pubkey
		KeyFactory pubKeyGen = KeyFactory.getInstance("rsa");
		FileInputStream input = new FileInputStream(User.currentUser + ".pub");
		int length = input.available();
		byte[] byteKey = new byte[length];
		input.read(byteKey);
		input.close();
		user_pub_key = null;
		X509EncodedKeySpec pubKeySpecs = new X509EncodedKeySpec(byteKey);
		user_pub_key = pubKeyGen.generatePublic(pubKeySpecs);
	}

	/**
	 * Reads the private key file, and sets the private variable user_private_key to the correct private key
	 * 
	 * @return Void
	 * @throws NoSuchAlgorithmException 
	 * @throws IOException 
	 * @throws InvalidKeySpecException 
	 */
	private static void setUserPrivateKey() throws NoSuchAlgorithmException, IOException, InvalidKeySpecException
	{
		//look in file user.privkey
		KeyFactory privKeyGen = KeyFactory.getInstance("rsa");
		FileInputStream input = new FileInputStream(User.currentUser + ".pri");
		int length = input.available();
		byte[] byteKey = new byte[length];
		input.read(byteKey);
		input.close();
		user_private_key = null;
		PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(byteKey);
		user_private_key = privKeyGen.generatePrivate(priKeySpec);
		
	}
	/**
	 * Takes in a Secret Key and encrypts it using RSA encryption
	 * 
	 * @return Void
	 * @throws IOException 
	 * @throws NoSuchAlgorithmException 
	 * @throws InvalidKeySpecException 
	 * @throws NoSuchPaddingException 
	 * @throws InvalidKeyException 
	 * @throws BadPaddingException 
	 * @throws IllegalBlockSizeException 
	 */
	public static String encryptSecretKey (String text) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
	{
		setUserPubKey();
		
		encrypter = Cipher.getInstance("rsa");
		encrypter.init(Cipher.ENCRYPT_MODE, user_pub_key);

		// Encode the string into bytes using utf-8
		byte[] utf8 = text.getBytes("UTF8");
		// Encrypt
		byte[] enc = encrypter.doFinal(utf8);

		clearKeys();
		// Encode bytes to base64 to get a string
		return new sun.misc.BASE64Encoder().encode(enc);
	}
	/**
	 * Takes in an RSA encrypted key and Decrypts it
	 * 
	 * @return Void
	 * @throws IOException 
	 * @throws InvalidKeySpecException 
	 * @throws NoSuchAlgorithmException 
	 * @throws NoSuchPaddingException 
	 * @throws InvalidKeyException 
	 * @throws BadPaddingException 
	 * @throws IllegalBlockSizeException 
	 */
	public static String decryptSecretKey (String text) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
	{
		setUserPrivateKey();
		
		decrypter = Cipher.getInstance("rsa");
		decrypter.init(Cipher.DECRYPT_MODE, user_private_key); 
		
		// Decode base64 to get bytes
		byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(text);
		// Decrypt
		byte[] utf8 = decrypter.doFinal(dec);
		
		clearKeys();
		// Decode using utf-8
		return new String(utf8, "UTF8"); 

	}
}